package com.designpattern.design.interpreter;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

public class InerpreterTest {

	
	public static void main(String[] args) {
		String expStr;
		try {
			expStr = getExpStr();
			HashMap<String, Integer> var = getValue(expStr);// var {a=10, b=20}
			Calculator calculator = new Calculator(expStr);
			System.out.println("运算结果：" + expStr + "=" + calculator.run(var));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} // a+b

		
	}
	// 获得表达式
	public static String getExpStr() throws IOException {
		System.out.print("请输入表达式：");
		return (new BufferedReader(new InputStreamReader(System.in))).readLine();
	}

	// 获得值映射
	public static HashMap<String, Integer> getValue(String expStr) throws IOException {
		HashMap<String, Integer> map = new HashMap<>();

		for (char ch : expStr.toCharArray()) {
			if (ch != '+' && ch != '-') {
				if (!map.containsKey(String.valueOf(ch))) {
					System.out.print("请输入" + String.valueOf(ch) + "的值：");
					String in = (new BufferedReader(new InputStreamReader(System.in))).readLine();
					map.put(String.valueOf(ch), Integer.valueOf(in));
				}
			}
		}

		return map;
	}
	
}

/**
 * 解析器接口
 * 定义解析方法
 * @author 15790
 *
 */
interface Expression{
	//传入具体参数进行解析-都得到结果
	int interpreter(Map<String,Integer> var);
}

/**
 * 变量解析器
 * @author 15790
 *
 */
class VarExpression implements Expression{

	private String key;
	
	public VarExpression(String key) {
		super();
		this.key = key;
	}

	@Override
	public int interpreter(Map<String,Integer> var) {
		// TODO Auto-generated method stub
		return var.get(key);
	}
	
}
/**
 * 符号解析器-抽象类 定义符号左右两边的变量
 * 左右两边都可能是解析之后产生的结果所以都是接口对象
 * 具体调用交给实现类来调用
 * @author 15790
 *
 */
abstract class SymbolExpression implements Expression{
	
	private Expression left;
	private Expression right;
	

	public Expression getLeft() {
		return left;
	}


	public void setLeft(Expression left) {
		this.left = left;
	}


	public Expression getRight() {
		return right;
	}


	public void setRight(Expression right) {
		this.right = right;
	}


	public SymbolExpression(Expression left, Expression right) {
		super();
		this.left = left;
		this.right = right;
	}
	/**
	 * 注意，这由于是抽象的符号解析器 所以这里不是先解析逻辑
	 * 交给具体的符号解析器来实现逻辑
	 */
}

/**
 * 加号解析器
 * 解析逻辑 将左右两边的解析器结果相加
 * @author 15790
 *
 */
class AddExpression extends SymbolExpression{

	public AddExpression(Expression left, Expression right) {
		super(left, right);
		// TODO Auto-generated constructor stub
	}

	@Override
	public int interpreter(Map<String, Integer> var) {
		// TODO Auto-generated method stub
		return super.getLeft().interpreter(var) + super.getRight().interpreter(var);
	}
	
}
/**
 * 减号解析器
 * 解析逻辑:将左右两边的解析器结果相减
 * @author 15790
 *
 */
class SubExpression extends SymbolExpression{

	public SubExpression(Expression left, Expression right) {
		super(left, right);
		// TODO Auto-generated constructor stub
	}

	@Override
	public int interpreter(Map<String, Integer> var) {
		// TODO Auto-generated method stub
		return super.getLeft().interpreter(var)-super.getRight().interpreter(var);
	}
	
}

/**
 * 乘法解析器
 * 执行顺序优先于加减解析器 没有括号的情况
 * 逻辑 两边相乘
 * @author 15790
 *
 */
class MultExpression extends SymbolExpression{

	public MultExpression(Expression left, Expression right) {
		super(left, right);
		// TODO Auto-generated constructor stub
	}

	@Override
	public int interpreter(Map<String, Integer> var) {
		// TODO Auto-generated method stub
		return super.getLeft().interpreter(var) * super.getRight().interpreter(var);
	}
	
}


/**
 * 计算器工具类 -实现符号解析
 * 
 * @author 15790
 *
 */
class Calculator{
	
	//定义表达式
	private Expression  expression;
	
	//构造表达式,并且解析
	public Calculator(String expStr) {
		//安排解析先后顺序  利用到栈来做数据存储
		Stack<Expression> stack=new Stack();
		// 表达式拆分成字符数组 
		char[] charArray = expStr.toCharArray();// [a, +, b]
		Expression left=null;
		Expression right=null;
		for(int i=0;i<charArray.length;i++) {
			switch (charArray[i]) {
			case '+':
				//把栈顶那一个拿出来
				left=stack.pop();
				//把后面那一个参数拿出来
				right=new VarExpression(String.valueOf(charArray[++i]));
				//计算之后将结果放到栈顶去
				stack.push(new AddExpression(left, right));
				break;
			case '-':
				//把栈顶那一个拿出来
				left=stack.pop();
				//把后面那一个参数拿出来
				right=new VarExpression(String.valueOf(charArray[++i]));
				//计算之后将结果放到栈顶去
				stack.push(new SubExpression(left, right));
				break;	
			default:
				//参数表达式
				stack.push(new VarExpression(String.valueOf(charArray[i])));
				break;
			}
		}
		//当遍历完之后 最后得到最后表达式
		this.expression=stack.pop();
	}
	
	/**
	 * 将表达式和参数绑定
	 * @param map
	 */
	public int run(Map<String,Integer> var) {
		return this.expression.interpreter(var);
	}
}
